package cus.area.util;

import cn.hutool.core.util.StrUtil;
import cus.area.util.constants.AreaData;
import cus.area.util.entity.Area;
import cus.area.util.entity.AreaEnum;

import java.util.LinkedHashMap;
import java.util.Map;

import static cus.area.util.constants.AreaData.*;

public class AreaUtils {
    /**
     * 手机号正则
     */
    public static String mobile = "(86-[1][0-9]{10})|(86[1][0-9]{10})|([1][0-9]{10})|([1][0-9]{2} [0-9]{4} [0-9]{4})|([1][0-9]{6} [0-9]{4})|([1][0-9]{6}-[0-9]{4})";
    /**
     * 座机号正则
     */
    public static String phone = "(([0-9]{3,4}-)[0-9]{7,8})|([0-9]{12})|([0-9]{11})|([0-9]{10})|([0-9]{9})|([0-9]{8})|([0-9]{7})";
    /**
     * 邮编正则
     */
    public static String zipCode = "([0-9]{6})";

    /**
     * 通过地区编码返回省市区对象
     *
     * @return 地址对象
     */
    public static Area getAreaByCode(String code) {
        String provinceCode = code.substring(0, 2) + "0000";
        String cityCode = code.substring(0, 4) + "00";
        return new Area.AreaBuilder().province(getNameByProvinceCode(provinceCode)).provinceCode(provinceCode).city(getNameByCityCode(cityCode)).cityCode(cityCode).county(getNameByCountyCode(code)).countyCode(code).build();
    }

    /**
     * 通过编码获取省市对象
     *
     * @param target 省,市枚举
     * @param code   编码,为地区,市,省
     * @return 地址对象
     */
    public static Area getTargetAreaByCode(AreaEnum target, String code) {
        Area.AreaBuilder builder = new Area.AreaBuilder();

        //code为地区
        if (!"00".equals(code.substring(4, 6))) {
            //地区
            builder.countyCode(code).county(getNameByCountyCode(code));
        }

        //code为市或地区,且目标需要省,市
        if (!"00".equals(code.substring(2, 4)) && (AreaEnum.PROVINCE.equals(target) || AreaEnum.CITY.equals(target))) {
            //市
            String cityCode = code.substring(0, 4) + "00";
            builder.cityCode(cityCode).city(getNameByCityCode(cityCode));
        }

        //目标需要省
        if (AreaEnum.PROVINCE.equals(target)) {
            String provinceCode = code.substring(0, 2) + "0000";
            builder.province(getNameByProvinceCode(provinceCode)).provinceCode(provinceCode);
        }

        return builder.build();
    }

    /**
     * 通过编码获取省市集合对象
     *
     * @param target 省,市枚举
     * @param code   编码,为地区,市,省
     * @return 地址对象
     */
    public static Map<String, String> getTargetsByCode(AreaEnum target, String code) {
        Map<String, String> targets = null;
        if (AreaEnum.PROVINCE.equals(target)) {
            String provinceCode = code.substring(0, 2);
            targets = putTargets(provinceCode, PROVINCES);
        } else if (AreaEnum.CITY.equals(target)) {
            String provinceCode = code.substring(0, 2);
            targets = putTargets(provinceCode, CITIES);
        } else if (AreaEnum.COUNTY.equals(target)) {
            if ("00".equals(code.substring(2, 4))) {
                String provinceCode = code.substring(0, 2);
                targets = putTargets(provinceCode, COUNTIES);
            } else {
                String cityCode = code.substring(0, 4);
                targets = putTargets(cityCode, COUNTIES);
            }
        }
        return targets;
    }

    /**
     * 标准化area对象
     *
     * @param area 地址对象
     * @return 地址对象
     */
    public static Area formatStandardArea(Area area) {
        String county = area.getCounty();
        String city = area.getCity();
        String province = area.getProvince();

        String provinceCodeTemp = null;
        String cityCodeTemp = null;

        for (Map.Entry<String, String> entry : AreaData.PROVINCES.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (StrUtil.isEmpty(provinceCodeTemp) && StrUtil.isNotEmpty(province) && value.contains(province)) {
                provinceCodeTemp = key.substring(0, 2);
                area.setProvinceCode(key);
                area.setProvince(value);
                break;
            }
        }

        for (Map.Entry<String, String> entry : AreaData.CITIES.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (StrUtil.isEmpty(cityCodeTemp) && StrUtil.equals(key.substring(0, 2), provinceCodeTemp) && StrUtil.isNotEmpty(city) && value.contains(city)) {
                cityCodeTemp = key.substring(0, 4);
                area.setCityCode(key);
                area.setCity(value);
                break;
            }
        }

        for (Map.Entry<String, String> entry : AreaData.COUNTIES.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (StrUtil.equals(key.substring(0, 4), cityCodeTemp) && StrUtil.isNotEmpty(county) && value.contains(county)) {
                area.setCountyCode(key);
                area.setCounty(value);
                break;
            }
        }
        return area;
    }

    /**
     * 根据名称获取地址
     *
     * @param target
     * @return
     */
    public static Area getAreaByName(Area target) {
        Area area = new Area();
        String province = target.getProvince();
        String city = target.getCity();
        String county = target.getCounty();

        String provinceCodeTemp = null;
        String cityCodeTemp = null;

        //封装省
        if (StrUtil.isNotEmpty(province)) {
            for (Map.Entry<String, String> entry : AreaData.PROVINCES.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                //省份不为空时,当enty为省份且还没有找到过省份
                if (value.contains(province) && StrUtil.equals("00", key.substring(2, 4))) {
                    provinceCodeTemp = key.substring(0, 2);
                    area.setProvinceCode(key);
                    area.setProvince(value);
                    break;
                }
            }
        }

        //封装市
        if (StrUtil.isNotEmpty(city)) {
            for (Map.Entry<String, String> entry : AreaData.CITIES.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                //市不为空时,当enty为市且还没有找到过市,如果已经找到省,则对比省是否一致,不一致则直接跳过
                boolean keyNotProvinceCodeTemp = StrUtil.isNotEmpty(provinceCodeTemp) && !StrUtil.equals(key.substring(0, 2), provinceCodeTemp);
                if (!keyNotProvinceCodeTemp && value.contains(city) && StrUtil.equals("00", key.substring(4, 6))) {
                    cityCodeTemp = key.substring(0, 4);
                    area.setCityCode(key);
                    area.setCity(value);
                    break;
                }
            }
        }

        ////封装区
        if (StrUtil.isNotEmpty(county)) {
            for (Map.Entry<String, String> entry : AreaData.COUNTIES.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                //当区不为空时,当entry为地区,还没有找到过地区,如果已经找到省,市,则优先对比省,市是否一致,不一致则直接跳过
                boolean keyNotProvinceCodeTemp = StrUtil.isNotEmpty(provinceCodeTemp) && !StrUtil.equals(key.substring(0, 2), provinceCodeTemp);
                boolean keyNotCityCodeTemp = StrUtil.isNotEmpty(cityCodeTemp) && !StrUtil.equals(key.substring(0, 4), cityCodeTemp);
                if (!keyNotProvinceCodeTemp && !keyNotCityCodeTemp && value.contains(county) && !StrUtil.equals("00", key.substring(4, 6))) {
                    area.setCountyCode(key);
                    area.setCounty(value);
                    break;
                }
            }
        }

        /*上面循环封装出了省,市,区,会出现没有市,省情况,则需要补充市,区*/
        //根据countyCode去补充city
        if (StrUtil.isEmpty(area.getCityCode()) && StrUtil.isNotEmpty(area.getCountyCode())) {
            String cityCode = area.getCountyCode().substring(0, 4) + "00";
            area.setCityCode(cityCode);
            area.setCity(getNameByCityCode(cityCode));
        }

        //根据cityCode去补充province
        if (StrUtil.isEmpty(area.getProvinceCode()) && StrUtil.isNotEmpty(area.getCityCode())) {
            String provinceCode = area.getCityCode().substring(0, 2) + "0000";
            area.setProvinceCode(provinceCode);
            area.setProvince(getNameByProvinceCode(provinceCode));
        }

        return area;
    }

    /**
     * 查找sources中key以preCode开头的对象,并存储到targets中
     * 其中break必须要依赖于数据是有一定顺序的,必须targets记录在同一范围,中间不能插入其他对象
     *
     * @param preCode
     * @param sources
     */
    private static Map<String, String> putTargets(String preCode, Map<String, String> sources) {
        Map<String, String> targets = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : sources.entrySet()) {
            int index = entry.getKey().indexOf(preCode);
            if (index == 0) {
                targets.put(entry.getKey(), entry.getValue());
            } else if (targets.size() > 0 && index != 0) {
                break;
            }
        }
        return targets;
    }
}
